package android.material.widget;

import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.material.util.NavigationIcon;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.material.util.Util;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import hd.util.ScreenHelper;

/**
 * 导航图
 * <p/>
 * Created by Haidy on 15/1/1.
 */
public class NavigationView extends View {

    private static final short ANIMATION_DURATION = 200;
    public static final int NAV_ICON = 0;
    public static final int NAV_BACK = 1;
    private final Paint paint;
    private boolean pressed = false;//当前是否按下
    private boolean animStop = true;//动画是否停止
    private int circleRadius = 0;//当前圆的半径
    private long animStartTime;
    private Point point = new Point();
    private final int ANIM_RATE = ScreenHelper.dp2px(getContext(), 40); //动画的速率
    private final int ANIM_ACC_RATE = ScreenHelper.dp2px(getContext(), 1);//失去焦点加速的速率
    private int currentAnimRate = 0;//当前速率
    private int currentAlpha = 0;
    private int currentBackgroundAlpha = 0;
    private Rect rect;
    private int backgroundColor;
    private float r;

    private Rect iconRect;

    private Bitmap icon = null;
    private int type = NAV_ICON;//导航图标的类型

    public NavigationView(Context context) {
        this(context, null);
    }

    public NavigationView(Context context, AttributeSet attrs) {
        super(context, attrs);
        if (attrs != null) {
            TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.NavigationView);
            int length = attributes.getIndexCount();
            for (int i = 0; i < length; i++) {
                int attr = attributes.getIndex(i);
                if (attr == R.styleable.NavigationView_nav_icon) {
                    type = attributes.getInt(attr, 0);
                }
            }
            attributes.recycle();
        }
        paint = new Paint();
        paint.setStyle(Paint.Style.FILL);
        paint.setAntiAlias(true);
        //icon大小
        int padding = ScreenHelper.dp2px(getContext(), 16);
        int size = ScreenHelper.dp2px(getContext(), 20);
        iconRect = new Rect(padding, padding, padding + size, padding + size);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int height = getContext().getResources().getDimensionPixelSize(R.dimen.titleBarHeight);
        r = (float) Math.ceil(height * Math.sqrt(2) / 2);
        int width = MeasureSpec.getSize((int) (height / 2 + r));
        setMeasuredDimension(width, height);
    }

    /**
     * 设置导航视图的类型
     *
     * @param type type
     */
    public void setType(int type) {
        this.type = type;
    }

    /**
     * 设置图标
     *
     * @param icon 图标
     */
    public void setIcon(Bitmap icon) {
        if (this.icon != icon) {
            this.icon = icon;
            invalidate();
        }
    }

    @Override
    public boolean onTouchEvent(@NonNull MotionEvent event) {
        rect = new Rect(0, 0, getHeight(), getHeight());
        super.onTouchEvent(event);
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                pressed = true;//按下
                point.x = (int) event.getX();
                point.y = (int) event.getY();//记录按下的位置
                animStop = false;
                circleRadius = 0;
                animStartTime = System.currentTimeMillis();//记录开始的时间
                currentAnimRate = ANIM_RATE;
                currentBackgroundAlpha = 0;
                paint.setAlpha(currentAlpha = 0x20);
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                Point p = new Point((int) event.getX(), (int) event.getY());
                if (!Util.inRect(p, rect)) {
                    actionUp();
                    return false;
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL://取消和抬起是一个效果
                actionUp();
                break;
        }
        return true;
    }

    private void actionUp() {
        postDelayed(new Runnable() {
            @Override
            public void run() {
                pressed = false;//抬起
                invalidate();//快速的消失波纹
            }
        }, 100);
    }

    @Override
    public void setBackgroundColor(int backgroundColor) {
        super.setBackgroundColor(backgroundColor);
        this.backgroundColor = backgroundColor;
    }

    private PorterDuffXfermode porterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP);

    @Override
    protected void onDraw(@NonNull Canvas canvas) {
        paint.setColor(backgroundColor);
        int sc = canvas.saveLayer(0, 0, getWidth(), getHeight(), null,
                Canvas.MATRIX_SAVE_FLAG |
                        Canvas.CLIP_SAVE_FLAG |
                        Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
                        Canvas.FULL_COLOR_LAYER_SAVE_FLAG |
                        Canvas.CLIP_TO_LAYER_SAVE_FLAG);
        canvas.drawCircle(getWidth() - r, getHeight() / 2, r, paint);
        paint.setXfermode(porterDuffXfermode);
        if (pressed) {
            if (Util.circleInRect(circleRadius, point, rect)) {
                if (currentBackgroundAlpha < 0x20)
                    currentBackgroundAlpha++;
                paint.setColor(Color.argb(currentBackgroundAlpha, 0, 0, 0));
                canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
                long time = System.currentTimeMillis() - animStartTime;
                circleRadius = Math.round(time * ANIM_RATE / ANIMATION_DURATION);
                paint.setColor(Color.argb(currentAlpha, 0, 0, 0));
                canvas.drawCircle(point.x, point.y, circleRadius, paint);
                invalidate();
            } else {//画出最后一帧结束
                paint.setColor(Color.argb(currentBackgroundAlpha, 0, 0, 0));
                canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
                paint.setColor(Color.argb(currentAlpha, 0, 0, 0));
                canvas.drawCircle(point.x, point.y, circleRadius, paint);
                animStop = true;
            }
        } else {
            if (animStop) {
                if (currentAlpha > 0 || currentBackgroundAlpha > 0) {
                    currentAlpha -= 2;//透明度变化的速率
                    currentAlpha = currentAlpha < 0 ? 0 : currentAlpha;
                    paint.setColor(Color.argb(currentAlpha, 0, 0, 0));
                    canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
                    --currentBackgroundAlpha;
                    currentBackgroundAlpha = currentBackgroundAlpha < 0 ? 0 : currentBackgroundAlpha;
                    paint.setColor(Color.argb(currentBackgroundAlpha, 0, 0, 0));
                    canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
                    invalidate();
                }
            } else {//动画还没消失，就快速扩大到最大半径
                if (Util.circleInRect(circleRadius, point, rect)) {
                    long time = System.currentTimeMillis() - animStartTime;
                    currentAnimRate += ANIM_ACC_RATE;//松手时加快的速率，越大扩散速度越快
                    circleRadius = Math.round(time * currentAnimRate / ANIMATION_DURATION);
                    paint.setColor(Color.argb(currentBackgroundAlpha, 0, 0, 0));
                    canvas.drawRect(0, 0, getWidth(), getHeight(), paint);

                    paint.setColor(Color.argb(currentAlpha, 0, 0, 0));
                    canvas.drawCircle(point.x, point.y, circleRadius, paint);
                    invalidate();
                } else {//画出最后一帧结束
                    paint.setColor(Color.argb(currentBackgroundAlpha, 0, 0, 0));
                    canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
                    paint.setColor(Color.argb(currentAlpha, 0, 0, 0));
                    canvas.drawCircle(point.x, point.y, circleRadius, paint);
                    animStop = true;
                    invalidate();
                }
            }
        }
        paint.setXfermode(null);
        canvas.restoreToCount(sc);
        if (icon != null && !icon.isRecycled()) {//icon
            canvas.drawBitmap(icon, iconRect, iconRect, null);
        } else {
            NavigationIcon.drawNavigation(canvas, this, type);
        }
        super.onDraw(canvas);
    }

}